using Microsoft.VisualStudio.TestTools.UnitTesting;
using Pegasus.Log4Net;
using Pegasus.Log4Net.Appender;
using Pegasus.Log4Net.Config;
using Pegasus.Log4Net.Core;
using Pegasus.UnitTests.Reflections;
using System;

namespace Pegasus.UnitTests
{
    [TestClass]
    public class MethodRepeaterTest
    {
        private const string RETRY_MSG = "try again";
        private const int NUM_TRIES = 5;

        Pegasus.MethodRepeater.VoidDelegate methodToRun = delegate()
        {
            throw new Exception( RETRY_MSG );
        };

        [TestMethod]
        public void TestMethodRepeater()
        {
            TestMethodRepeater( true );
            TestMethodRepeater( false );
        }

        private void TestMethodRepeater( bool logExceptions )
        {
            bool caughtException = false;
            ILog logger = null;
            MemoryAppender memAppender = null;

            if( logExceptions )
            {
                memAppender = new MemoryAppender();
                memAppender.Threshold = Level.Debug;
                BasicConfigurator.Configure( memAppender );
                logger = LogManager.GetLogger( typeof( MethodRepeaterTest ) );
            }

            try
            {
                MethodRepeater.RepeatMethod( methodToRun, logger, Level.Debug, NUM_TRIES );
            }
            catch
            {
                caughtException = true;
            }

            // make sure that it threw an exception.
            Assert.IsTrue( caughtException );

            if( logExceptions )
            {
                // perform checks for logging.
                LoggingEvent[] events = memAppender.GetEvents();
                Assert.IsNotNull( events );
                Assert.AreEqual<int>( NUM_TRIES - 1, events.Length );

                foreach( LoggingEvent e in events )
                {
                    Assert.AreEqual<Level>( Level.Debug, e.Level );
                    Assert.AreEqual<string>( RETRY_MSG, e.ExceptionObject.Message );
                    Assert.AreEqual<string>( "Pegasus.UnitTests.MethodRepeaterTest", e.LocationInformation.ClassName );
                    Assert.AreEqual<string>( "TestMethodRepeater", e.LocationInformation.MethodName );
                }
            }
        }
    }
}
